package corelayer;

import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * 物理デバイスのインターフェイスと論理ノードのインターフェイスを仲介します
 */
public class Device implements IDevice {

    private IRawDevice rawDevice;
    private PacketBuilder builder;

    public Device(IRawDevice rawDevice, PacketBuilder builder) {
        if (rawDevice == null) {
            throw new IllegalArgumentException("rawDevice is null");
        }
        if (builder == null) {
            throw new IllegalArgumentException("builder is null");
        }
        this.builder = builder;
        this.rawDevice = rawDevice;
    }

    public Device(IRawDevice rawDevice) {
        this(rawDevice, new PacketBuilder());
    }

    @Override
    public void send(IPacket packet) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutput out = new DataOutputStream(bos);
        byte[] data = null;
        try {
            packet.packTo(out);
            data = bos.toByteArray();
            bos.close();
        } catch (IOException packEx) {
            // pack処理は通常失敗しないので
            // 失敗したらAbort
            throw new RuntimeException(packEx);
        }

        try {
            this.rawDevice.send(data);
        } catch (IOException sendEx) {
            // 送信処理は失敗するかも知れないので
            // メッセージ出して続行
            System.out.println("Failed to send packet");
            System.out.println(sendEx.getMessage());
        }
    }

    @Override
    public IPacket recv() {
        byte[] data = this.rawDevice.recv();
        if (data != null) {
            return builder.unpack(data);
        } else {
            return null;
        }
    }
}
